#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/device.h>

#define PERR(msg) do {	\
	printk("error: %s\n", msg);	\
	printk("error at: %s:%s %d\n", __FILE__, __func__, __LINE__);	\
}while(0)

ssize_t demo_read(struct file *file, char __user *ubuf, size_t size, loff_t *offset)
{
	printk("%s invoked\n", __func__);
	return size;
}



ssize_t demo_write(struct file *file, const char __user *ubuf, size_t size, loff_t *offset)
{
	printk("%s invoked\n", __func__);

	return size;
}

int demo_open(struct inode *inode, struct file *file)
{
	printk("%s invoked\n", __func__);

	return 0;
}

int demo_close(struct inode *inode, struct file *file)
{
	printk("%s invoked\n", __func__);

	return 0;
}


unsigned int major =  666;
unsigned int minor = 0;
const char *devname = "demodev";
struct class *cls;
struct device *dev;
const struct file_operations fops = {
	.read 		= demo_read,
	.write 		= demo_write,
	.open		= demo_open,
	.release 	= demo_close,
};

// 入口函数
static int __init init_func(void)
{
	printk("init invoked.\n");
	// 自动注册字符设备驱动
	major = register_chrdev(0, devname, &fops);

	if(major < 0){
		PERR("register_chrdev");
		goto ERR1;
	}

	// 自动创建字符设备驱动文件
	cls = class_create(THIS_MODULE, devname);

	if (cls == NULL){
		PERR("class_create");
		goto ERR2;
	}
	
	dev = device_create(cls, NULL, MKDEV(major, minor), NULL, devname);
	if (dev == NULL) {
		PERR("device_create");
		goto ERR3;
	}

ERR3:
	class_destroy(cls);

ERR2:
	unregister_chrdev(MKDEV(major, minor), devname);

ERR1:
	return 0;
}

// 出口函数
static void __exit exit_func(void)
{
	printk("exit invoked.\n");
	device_destroy(cls, MKDEV(major, minor));
	class_destroy(cls);
	unregister_chrdev(MKDEV(major, minor), devname);
}

module_init(init_func);
module_exit(exit_func);
MODULE_LICENSE("GPL");







